package com.itlong.cloud.smartcard.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.operate.ProjectSmartCommunityStatusChangeDTO;
import com.itlong.cloud.POJO.DTO.property.HouseHoldManageJPushDTO;
import com.itlong.cloud.POJO.DTO.smartcard.SmartCardOldAuthDoorDTO;
import com.itlong.cloud.POJO.DTO.smartcard.SmartCardOldAuthFloorDTO;
import com.itlong.cloud.POJO.DTO.smartcard.SmartCardOldUserInfoDTO;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.smartcard.SmartCardOldLoginVO;
import com.itlong.cloud.POJO.VO.smartcard.SmartCardOldUserInfoVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.property.dao.*;
import com.itlong.cloud.property.service.IPropertyHouseHoldInfoService;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.smartcard.dao.ISmartCardOldUserInfoDao;
import com.itlong.cloud.smartcard.service.ISmartCardOldUserInfoService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.NumberHandlerUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <desc>
 *       旧一卡通—用户模块服务接口实现类。
 * <desc/>
 *
 * @createDate 2017/11/1.
 */
@Service
@RefreshScope
public class SmartCardOldUserInfoServiceImpl implements ISmartCardOldUserInfoService {
    private static final Logger LOG = LoggerFactory.getLogger(SmartCardOldUserInfoServiceImpl.class);

     // 旧一卡通_用户模块操作数据库接口
     @Autowired
     ISmartCardOldUserInfoDao iSmartCardOldUserInfoDao;

     //redis缓存
     @Autowired
     RedisService redisService;

     //app凭证加密key
    @Value("${" + PlatformConstants.APP_USER_TOKEN_KEY + "}")
    String userTokenKey;

    //云对讲发送指令
    @Autowired
    MessageSender messageSender;


    //App用户信息数据库访问对象
    @Autowired
    private IPropertyAppUserInfoDao iPropertyAppUserInfoDao;
    //App用户项目信息数据库访问对象
    @Autowired
    private IPropertyAppUserProjectDao iPropertyAppUserProjectDao;
    @Autowired
    private IPropertyAppUserRoomDao iPropertyAppUserRoomDao;

    //电梯授权
    @Autowired
    private IPropertyDeviceElevatorAuthDao iPropertyDeviceElevatorAuthDao;
    //门禁授权
    @Autowired
    private IPropertyDeviceEntranceAuthDao iPropertyDeviceEntranceAuthDao;

    @Autowired
    IPropertyHouseHoldInfoService iPropertyHouseHoldInfoService;



      /**
       * <desc>
       *      旧一卡通登录。
       * <desc/>
       *
       * @param  account 用戶名
       * @return  pswd  密码
       * @author shengen.T
       * @createDate 2017/11/2
       */
     @Override
     @Transactional(rollbackFor = Exception.class,propagation = Propagation.NOT_SUPPORTED)
     public SmartCardOldLoginVO login(String account, String pswd) throws Exception{
         //判断账号和密码的真实性
          if((!account.equals(PlatformConstants.OLD_SMARTCARD_LOGIN_USER))||(!pswd.equals(PlatformConstants.OLD_SMARTCARD_LOGIN_PASSWORD))){
               return null;
          }
          SmartCardOldLoginVO voLogin = new SmartCardOldLoginVO();
          String token  = UserTokenUtil.tokenEncrypt(account,userTokenKey, SystemTypeEnum.IOS.getType());
          voLogin.setToken(token);
          voLogin.setUserName(account);
          //将当前登录用户添加进缓存
          redisService.set(RedisConstant.OLD_APP_USER_VO_KEY+account, JSON.toJSONString(voLogin));
          return voLogin;
     }

      /**
       * <desc>
       *      查询单个用户的所有信息列表。
       * <desc/>
       *
       * @param  phoneNo 手机号码
       * @return
       * @author shengen.T
       * @createDate 2017/11/2
       */
     @Override
     @Transactional(rollbackFor = Exception.class,propagation = Propagation.NOT_SUPPORTED)
     public List<SmartCardOldUserInfoVO> getUserInfoList( String phoneNo) throws Exception {
          return iSmartCardOldUserInfoDao.getUserInfoList(phoneNo);
     }

      /**
       * <desc>
       *      一卡通检测手机号是否存在。
       * <desc/>
       *
       * @param  phoneNo 返回
       * @return true 存在 false 不存在
       * @author shengen.T
       * @createDate 2017/11/3
       */
     @Override
     @Transactional(rollbackFor = Exception.class,propagation = Propagation.NOT_SUPPORTED)
     public boolean checkPhone(String phoneNo) throws Exception{
       boolean result = false;
       Integer count = iSmartCardOldUserInfoDao.checkPhone(phoneNo);
       if(count>=1){
            result =  true;
       }
       return result;
     }

     /**
      * <desc>
      *      旧一卡通_修改用户事务
      * <desc/>
      *
      * @param updateDTO 更新信息
      * @return
      * @author Chunjian.G
      * @createDate 2018-02-25
      */
     @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
     public Map<String, Object> updateTrans(SmartCardOldUserInfoDTO updateDTO) throws Exception{
         Map<String, Object> resultMap = new HashMap<>();
         String userId = iSmartCardOldUserInfoDao.getUserIdByPhoneNo(updateDTO.getUpdatePhoneNo());
         if(StringUtils.isBlank(userId)){
             return null;
         }
         Integer res = null;
         if("0".equals(updateDTO.getUserStatus())){ //解冻
             res = iSmartCardOldUserInfoDao.updateStatus(userId, updateDTO.getProjectId(),
                     updateDTO.getCardNum(), AppUserProjectStatusEnum.USERPROJECT_USERPROJECTSTATUS_ENABLE.getType());
         }else if("1".equals(updateDTO.getUserStatus())){  //冻结
             res = iSmartCardOldUserInfoDao.updateStatus(userId, updateDTO.getProjectId(),
                     updateDTO.getCardNum(), AppUserProjectStatusEnum.USERPROJECT_USERPROJECTSTATUS_FROZEN.getType());
         }

         resultMap.put("result", res);
         //用户是否已在app端注册
         resultMap.put("hasRegistered", NumberHandlerUtil.isGreaterThan(iSmartCardOldUserInfoDao.checkPhone(updateDTO.getUpdatePhoneNo()), 0));
         //用户id
         resultMap.put("userId", userId);

         return resultMap;
     }

     /**
      * <desc>
      *      发送用户信息变更通知
      * <desc/>
      *
      * @param userId 用户id
      * @param updateDTO 更新数据
      * @return
      * @author Chunjian.G
      * @createDate 2018-02-25
      */
     private void sendUserChangeMessage(String userId, SmartCardOldUserInfoDTO updateDTO) throws Exception{
        //1.刷新权限变更
         sendMessageForUserAuthChanged(userId,updateDTO.getProjectId());

         //2.若项目启用云对讲则需推送云对讲指令
         if (ProjectSmartCommunityStatusEnum.PROJECT_SMART_COMMUNITY_YES.getType().equals(updateDTO.getIsSmartCommunity())){
             //用户项目关系变更
             List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
             JSONObject json = new JSONObject();
             json.put("userId", userId);
             json.put("projectId", updateDTO.getProjectId());
             DeviceBusinessChangeLogPO deviceBusinessChangeLogPO =
                     new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_USER_PROJECT, json, updateDTO.getProjectId());
             changeLogPOS.add(deviceBusinessChangeLogPO);
             JSONObject dataJs = new JSONObject();
             dataJs.put("data",changeLogPOS);
             messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                     JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                     RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);

             //云电梯
             DeviceBusinessElevatorChangeLogPO elevatorLogPO
                     = new DeviceBusinessElevatorChangeLogPO(updateDTO.getProjectId(),
                     CloudElevatorChangeBusinessEnum.PUSH_USER_PROJECT,json.toJSONString());
             List<DeviceBusinessElevatorChangeLogPO> elevatorLogPOS = new ArrayList<>();
             elevatorLogPOS.add(elevatorLogPO);
             dataJs.put("data",elevatorLogPOS);
             messageSender.send(
                     RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                     JsonUtil.toJSON(dataJs),
                     RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                     RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
             //LOG.info(String.format("消息通知云对讲用户项目变更：projectId-%s，userId-%s", updateDTO.getProjectId(), userId));

             // 云门禁
             List<DeviceBusinessEntranceChangeLogPO> changeEntranceLogPOS = new ArrayList<>();
             changeEntranceLogPOS.add(new DeviceBusinessEntranceChangeLogPO(CloudEntranceChangeBusinessEnum.PUSH_USER_PROJECT, json, updateDTO.getProjectId()));
             dataJs.put("data", changeEntranceLogPOS);
             //发送云门禁指令
             messageSender.send(
                     RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                     JSON.toJSONString(dataJs),
                     RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                     RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
             );

             //业主房间密码有效性变更
             List<String> userIds = new ArrayList<>();
             userIds.add(userId);
             Map<String, Object> param = new HashMap<>();
             param.put("userIds", userIds);
             param.put("projectId", updateDTO.getProjectId());
             List<AppUserRoomPO> appUserRoomPOS = iPropertyAppUserRoomDao.getHouseHoldRoomAtNormalStatus(param);
             if (appUserRoomPOS != null && appUserRoomPOS.size() > 0) {
                 JSONArray roomArr = new JSONArray();
                 for (AppUserRoomPO roomPO:appUserRoomPOS) {
                     JSONObject room = new JSONObject();
                     room.put("roomId", roomPO.getRoomId());
                     roomArr.add(room);
                 }
                 //推送住户所有业主身份房间信息
                 //云对讲
                 List<DeviceBusinessChangeLogPO> roomChangeLogPOS = new ArrayList<>();
                 DeviceBusinessChangeLogPO roomChangeLogPO =
                         new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM, roomArr, updateDTO.getProjectId());
                 roomChangeLogPOS.add(roomChangeLogPO);
                 //云电梯
                 DeviceBusinessElevatorChangeLogPO deviceBusinessElevatorChangeLogPO
                         = new DeviceBusinessElevatorChangeLogPO(updateDTO.getProjectId(),
                         CloudElevatorChangeBusinessEnum.PUSH_ROOM_PWD,roomArr.toJSONString());
                 List<DeviceBusinessElevatorChangeLogPO> deviceElevatorChangeLogPOS = new ArrayList<>();
                 deviceElevatorChangeLogPOS.add(deviceBusinessElevatorChangeLogPO);
                 if (!roomChangeLogPOS.isEmpty()) {
                     JSONObject roomDataJs = new JSONObject();
                     roomDataJs.put("data",roomChangeLogPOS);
                     //云对讲推送
                     messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                             JsonUtil.toJSON(roomDataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                             RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
                     roomDataJs.put("data",deviceElevatorChangeLogPOS);
                     //云电梯推送
                     messageSender.send(
                             RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                             JsonUtil.toJSON(dataJs),
                             RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                             RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
                 }
                 //LOG.info(String.format("消息通知云对讲房间信息变更：%s", JSON.toJSONString(roomArr)));
             }
         }

         //3.极光推送用户状态变更推送指令
         Map<String,String> comands = new HashMap<>();
         comands.put("refreshSips", "1");
         //推送消息
         String msg = "您在{" + updateDTO.getProjectName() + "}的住户权限已";
         if ("0".equals(updateDTO.getUserStatus())) {
             //启用
             msg += "恢复...";
         } else {
             //冻结
             msg += "被冻结...";
         }
         List<HouseHoldManageJPushDTO> houseHoldManageJPushDTOS = new ArrayList<>();
         HouseHoldManageJPushDTO houseHoldManageJPushDTO = new HouseHoldManageJPushDTO();
         houseHoldManageJPushDTO.setMsg(msg);
         houseHoldManageJPushDTO.setPhoneNum(updateDTO.getUpdatePhoneNo());
         houseHoldManageJPushDTO.setProjectId(updateDTO.getProjectId());
         houseHoldManageJPushDTO.setComands(comands);
         houseHoldManageJPushDTOS.add(houseHoldManageJPushDTO);
         JSONObject dataJs = new JSONObject();
         dataJs.put("data",JSONObject.toJSON(houseHoldManageJPushDTOS));
         messageSender.send(RabbitMQConstant.RABBITMQ_HOUSEHOLD_JPUSH_QUEUE,
                 JSON.toJSONString(dataJs), RabbitMQConstant.RABBITMQ_HOUSEHOLD_JPUSH_EXCHANGE,
                 RabbitMQConstant.RABBITMQ_HOUSEHOLD_JPUSH_KEY);
     }

    /**
     * <desc>
     *      旧一卡通_修改用户。
     * <desc/>
     *
     * @param updateDTO 更新数据
     * @return 返回影响行数
     * @author shengen.T
     * @createDate 2017/11/3
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer update(SmartCardOldUserInfoDTO updateDTO) throws Exception{
        //1.更新用户信息
        Map<String, Object> resultMap = this.updateTrans(updateDTO);
        if (resultMap == null){
            return null;
        }
        //2.若用户已在app端注册，则发送用户信息变更相关消息通知
        if ((boolean) resultMap.get("hasRegistered")){
            this.sendUserChangeMessage((String) resultMap.get("userId"), updateDTO);
        }
        return (Integer) resultMap.get("result");
    }

    /**
     * <desc>
     *      旧一卡通_授权门禁事务
     * <desc/>
     *
     * @param authDoorDTO 门禁权限
     * @return
     * @author Chunjian.G
     * @createDate 2018-02-25
     */
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Map<String, Object> authDoorTrans(SmartCardOldAuthDoorDTO authDoorDTO) throws Exception{
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("isNewUser", false);//是否是新用户
        resultMap.put("isNewUserProject", false);//是否是该项目下的新用户

        //1.判断用户是否已存在(app_user_info)
        Map<String, Object> param = new HashMap<>();
        param.put("projectId", authDoorDTO.getProjectId());
        param.put("phoneNum", authDoorDTO.getAuthPhoneNo());
        List<AppUserInfoPO> appUserInfoPOS = iPropertyAppUserInfoDao.getUserInfoByPhoneNum(param);
        if (appUserInfoPOS != null && !appUserInfoPOS.isEmpty()){
            resultMap.put("userId", appUserInfoPOS.get(0).getUserId());//返回用户id

            //更新用户名
            if (StringUtils.isBlank(appUserInfoPOS.get(0).getRealName()) ||
                    !appUserInfoPOS.get(0).getRealName().equals(authDoorDTO.getAuthUserName())){
                appUserInfoPOS.get(0).setRealName(authDoorDTO.getAuthUserName());
                appUserInfoPOS.get(0).setUpdateTime(new Date());
                iPropertyAppUserInfoDao.update(appUserInfoPOS.get(0));
            }
            //已存在用户，判断用户-项目关系是否存在(app_user_project)
            List<AppUserProjectPO> userProjectPOS = iPropertyAppUserProjectDao.getUserAtProjectByPhoneNum(param);
            if (userProjectPOS != null && !userProjectPOS.isEmpty()){
                if (!NumberHandlerUtil.isEqual(userProjectPOS.get(0).getStatus(), DataStatusEnum.NORMAL.getType())){
                    userProjectPOS.get(0).setStatus(DataStatusEnum.NORMAL.getType());
                    userProjectPOS.get(0).setUpdateTime(new Date());
                    iPropertyAppUserProjectDao.update(userProjectPOS.get(0));
                }
                //用户-项目关系已存在，则添加/更新门禁权限(device_entrance_auth)
                this.saveOrUpdateEntranceAuth(authDoorDTO, userProjectPOS.get(0).getUserId());
            }else {
                resultMap.put("isNewUserProject", true);//该项目下的新用户

                //保存住户项目信息
                this.saveAppUserProject(appUserInfoPOS.get(0).getUserId(), authDoorDTO.getProjectId(), authDoorDTO.getCardNum());
                //保存门禁权限(device_entrance_auth)
                this.saveOrUpdateEntranceAuth(authDoorDTO, appUserInfoPOS.get(0).getUserId());
            }
        }else {
            //不存在用户则添加(app_user_info)
            AppUserInfoPO appUserInfoPO = new AppUserInfoPO();
            String userId = LogicIdUtil.userBusinessId();
            Date date = new Date();
            appUserInfoPO.setUserId(userId);
            appUserInfoPO.setRealName(authDoorDTO.getAuthUserName());
            appUserInfoPO.setPhoneNum(authDoorDTO.getAuthPhoneNo());
            appUserInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
            appUserInfoPO.setCreateTime(date);
            appUserInfoPO.setUpdateTime(date);
            iPropertyAppUserInfoDao.save(SqlUtil.durableData(appUserInfoPO, PlatformConstants.TABLE_SAVE));

            resultMap.put("isNewUser", true);//新用户
            resultMap.put("isNewUserProject", true);//该项目下的新用户
            resultMap.put("userId", userId);//返回用户id
            //添加用户-项目关系(app_user_project)
            this.saveAppUserProject(userId, authDoorDTO.getProjectId(), authDoorDTO.getCardNum());
            //添加门禁权限(device_entrance_auth)
            this.saveOrUpdateEntranceAuth(authDoorDTO, userId);
        }
        return resultMap;
    }

    /**
     * <desc>
     * 旧一卡通_授权门禁
     * <desc/>
     *
     * @param authDoorDTO 门禁权限
     * @return
     * @author Chunjian.G
     * @createDate 2017-12-09
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer authDoor(SmartCardOldAuthDoorDTO authDoorDTO, Integer isSmartCommunity) throws Exception {
        //1.保存授权数据
        Map<String, Object> resultMap = this.authDoorTrans(authDoorDTO);
        //2.若该项目启用了云对讲,且为该项目下的新用户，需发送同步sip消息
        if ((boolean) resultMap.get("isNewUserProject")){
            this.sendSipSyncMessage((String) resultMap.get("userId"), isSmartCommunity, authDoorDTO.getProjectId());
        }
        //3.原本已存在的用户需发送权限变更消息
        if (!(boolean) resultMap.get("isNewUser")){
            this.sendMessageForUserAuthChanged((String) resultMap.get("userId"), authDoorDTO.getProjectId());
        }
        return 1;
    }

    /**
     * <desc>
     *      添加新的住户项目关系后需要同步sip信息
     * <desc/>
     *
     * @param userId
     * @param isSmartCommunity
     * @param projectId
     * @return
     * @author Chunjian.G
     * @createDate 2018-02-26
     */
    private void sendSipSyncMessage(String userId, Integer isSmartCommunity, String projectId) throws Exception{
        //住户项目信息不存在时需新增SIP信息同时同步SIP信息（通知用户服务）
        if (ProjectSmartCommunityStatusEnum.PROJECT_SMART_COMMUNITY_YES.getType() == isSmartCommunity) {
            ProjectSmartCommunityStatusChangeDTO changeDTO = new ProjectSmartCommunityStatusChangeDTO();
            changeDTO.setProjectId(projectId);
            changeDTO.setIsSmartCommunity(isSmartCommunity);
            changeDTO.setUserId(userId);
            JSONObject dataJs = new JSONObject();
            dataJs.put("data", JSON.toJSON(changeDTO));
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_PROJECT_SMART_COMMUNITY_STATUS_QUEUE,
                    JSON.toJSONString(dataJs),
                    RabbitMQConstant.RABBITMQ_USER_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_PROJECT_SMART_COMMUNITY_STATUS_KEY
            );
            System.out.println(String.format("【%s】通知用户服务生成sip账号：projectId-%s，isSmartCommunity-%d，userId-%s",
                    DateUtil.fomatDate1(new Date()), projectId, isSmartCommunity, userId));
        }
    }
    /**
     * <desc>
     *      保存用户项目关系(app_user_project)
     * <desc/>
     *
     * @param
     * @return
     * @author Chunjian.G
     * @createDate 2017-12-15
     */
    private Integer saveAppUserProject(String userId, String projectId, String cardNum) throws Exception{
        AppUserProjectPO appUserProjectPO = new AppUserProjectPO();
        Date date = new Date();
        appUserProjectPO.setUserId(userId);
        appUserProjectPO.setProjectId(projectId);
        appUserProjectPO.setCardNum(cardNum);
        appUserProjectPO.setUserProjectStatus(String.valueOf(AppUserProjectStatusEnum.USERPROJECT_USERPROJECTSTATUS_ENABLE.getType()));
        appUserProjectPO.setStatus(DataStatusEnum.NORMAL.getType());
        appUserProjectPO.setUserType(AppUserProjectUserTypeEnum.USERPROJECT_USERTYPE_ORDINARY.getType());
        appUserProjectPO.setCreateTime(date);
        appUserProjectPO.setUpdateTime(date);
        return iPropertyAppUserProjectDao.save(SqlUtil.durableData(appUserProjectPO, PlatformConstants.TABLE_SAVE));
    }

    /**
     * <desc>
     *      添加/更新门禁权限(device_entrance_auth)
     * <desc/>
     *
     * @param
     * @return
     * @author Chunjian.G
     * @createDate 2017-12-12
     */
    private Integer saveOrUpdateEntranceAuth(SmartCardOldAuthDoorDTO authDoorDTO, String userId) throws Exception{
        Map<String, Object> mj = new HashMap<>();
        mj.put("authUserId", authDoorDTO.getProjectId());
        mj.put("projectId", authDoorDTO.getProjectId());
        mj.put("userId", userId);
        mj.put("authSource", DeviceAuthEnum.DEVICEAUTH_SMARTCARD.getType());
        //获取用户旧的设备权限信息
        //List<DeviceEntranceAuthPO> entranceAuthPOS = iPropertyDeviceEntranceAuthDao.getUserDeviceEntranceAuth(mj);
        List<Integer> authIds = iPropertyDeviceEntranceAuthDao.getUserDeviceEntranceAuthId(mj);

        DeviceEntranceAuthPO authPO = new DeviceEntranceAuthPO();
        authPO.setUserId(userId);
        authPO.setProjectId(authDoorDTO.getProjectId());
        authPO.setValiTime(DateUtil.formatLong(StringHandlerUtil.strToLongDef(authDoorDTO.getValiTime(),0)));
        authPO.setDeviceAuth(authDoorDTO.getHandledDoorAuth());
        authPO.setAuthSource(DeviceAuthEnum.DEVICEAUTH_SMARTCARD.getType());
        authPO.setAuthUserId(authDoorDTO.getProjectId());
        authPO.setStatus(DataStatusEnum.NORMAL.getType());
        authPO.setUpdateTime(new Date());
        authPO.setCreateTime(authPO.getCreateTime());
        if (authIds != null && !authIds.isEmpty()){
            Integer res = null;
            //先保存新记录
            if (StringUtils.isNotBlank(authDoorDTO.getDeviceUniques())){
                Map<String, Object> auth = SqlUtil.durableData(authPO, PlatformConstants.TABLE_SAVE);
                res = iPropertyDeviceEntranceAuthDao.save(auth);
            }
            //再删除原有的记录
            iPropertyDeviceEntranceAuthDao.deleteById(String.valueOf(authIds.get(0)));
            return res;
        }else {
            //添加
            if (StringUtils.isNotBlank(authDoorDTO.getDeviceUniques())){
                authPO.setCreateTime(authPO.getUpdateTime());
                Map<String, Object> auth = SqlUtil.durableData(authPO, PlatformConstants.TABLE_SAVE);
                return iPropertyDeviceEntranceAuthDao.save(auth);
            }
        }
        return null;
    }

    /**
     * <desc>
     *      添加/更新电梯权限(device_elevator_auth)
     * <desc/>
     *
     * @param
     * @return
     * @author Chunjian.G
     * @createDate 2017-12-15
     */
    private Integer saveOrUpdateElevatorAuth(SmartCardOldAuthFloorDTO authFloorDTO, String userId) throws Exception{
        Map<String, Object> params = new HashMap<>();
        params.put("authUserId", authFloorDTO.getProjectId());
        params.put("projectId", authFloorDTO.getProjectId());
        params.put("userId", userId);
        params.put("authSource", DeviceAuthEnum.DEVICEAUTH_SMARTCARD.getType());
        //获取用户旧的设备权限信息
        //List<DeviceElevatorAuthPO> elevatorAuthPOS = iPropertyDeviceElevatorAuthDao.getUserDeviceElevatorAuth(params);
        List<Integer> authIds = iPropertyDeviceElevatorAuthDao.getUserDeviceElevatorAuthId(params);

        DeviceElevatorAuthPO authPO = new DeviceElevatorAuthPO();
        authPO.setUserId(userId);
        authPO.setProjectId(authFloorDTO.getProjectId());
        authPO.setValiTime(DateUtil.formatLong(StringHandlerUtil.strToLongDef(authFloorDTO.getValiTime(),0)));
        authPO.setDeviceAuth(authFloorDTO.getHandledDeviceAuth());
        authPO.setFloorAuth(authFloorDTO.getHandledFloorAuth());
        authPO.setAuthSource(DeviceAuthEnum.DEVICEAUTH_SMARTCARD.getType());
        authPO.setAuthUserId(authFloorDTO.getProjectId());
        authPO.setStatus(DataStatusEnum.NORMAL.getType());
        authPO.setUpdateTime(new Date());
        authPO.setCreateTime(authPO.getUpdateTime());
        if (authIds != null && !authIds.isEmpty()){
            Integer res;
            //先保存新记录
            if (StringUtils.isNotBlank(authFloorDTO.getDeviceUniques())){
                Map<String, Object> auth = SqlUtil.durableData(authPO, PlatformConstants.TABLE_SAVE);
                res = iPropertyDeviceElevatorAuthDao.save(auth);
            }
            //后删除原有的记录
            res = iPropertyDeviceElevatorAuthDao.deleteById(String.valueOf(authIds.get(0)));
            return res;
        }else {
            //添加
            if (StringUtils.isNotBlank(authFloorDTO.getDeviceUniques())){
                authPO.setCreateTime(authPO.getUpdateTime());
                Map<String, Object> auth = SqlUtil.durableData(authPO, PlatformConstants.TABLE_SAVE);
                return iPropertyDeviceElevatorAuthDao.save(auth);
            }
        }
        return null;
    }

    /**
     * <desc>
     *      一卡通用户权限变更时发送通知消息
     * <desc/>
     *
     * @param
     * @return
     * @author Chunjian.G
     * @createDate 2017-12-18
     */
    private void sendMessageForUserAuthChanged(String userId, String projectId) throws Exception {
        //住户设备权限更新时通知后台移动App模块
        Map<String, Object> param = new HashMap<>();
        param.put("userId", userId);
        param.put("projectId", projectId);
        messageSender.send(RabbitMQConstant.RABBITMQ_EQUIP_APP_USER_INFO_DEVICE_UPDATE_QUEUE,
                JSON.toJSONString(param), RabbitMQConstant.RABBITMQ_EQUIP_EXCHANGE,
                RabbitMQConstant.RABBITMQ_EQUIP_APP_USER_INFO_DEVICE_UPDATE_KEY);

        //住户设备权限更新时通知后台移动App模块更新用户二维码
//        messageSender.send(RabbitMQConstant.RABBITMQ_EQUIP_APP_USER_QRCODE_UPDATE_QUEUE,
//                JSON.toJSONString(param), RabbitMQConstant.RABBITMQ_EQUIP_EXCHANGE,
//                RabbitMQConstant.RABBITMQ_EQUIP_APP_USER_QRCODE_UPDATE_KEY);
        //LOG.info(String.format("一卡通用户权限变更通知更新权限及二维码：projectId-%s，userId-%s", projectId, userId));
    }


    /**
     * <desc>
     *      旧一卡通_授权电梯事务
     * <desc/>
     *
     * @param authFloorDTO 电梯权限
     * @return
     * @author Chunjian.G
     * @createDate 2018-02-26
     */
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Map<String, Object> authFloorTrans(SmartCardOldAuthFloorDTO authFloorDTO) throws Exception{
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("isNewUser", false);//是否是新用户
        resultMap.put("isNewUserProject", false);//是否是该项目下的新用户

        //1.判断用户是否已存在(app_user_info)
        Map<String, Object> param = new HashMap<>();
        param.put("projectId", authFloorDTO.getProjectId());
        param.put("phoneNum", authFloorDTO.getAuthPhoneNo());
        List<AppUserInfoPO> appUserInfoPOS = iPropertyAppUserInfoDao.getUserInfoByPhoneNum(param);
        if (appUserInfoPOS != null && !appUserInfoPOS.isEmpty()){
            resultMap.put("userId", appUserInfoPOS.get(0).getUserId());//返回用户id

            //更新用户名
            if (StringUtils.isBlank(appUserInfoPOS.get(0).getRealName()) ||
                    !appUserInfoPOS.get(0).getRealName().equals(authFloorDTO.getAuthUserName())){
                appUserInfoPOS.get(0).setRealName(authFloorDTO.getAuthUserName());
                appUserInfoPOS.get(0).setUpdateTime(new Date());
                iPropertyAppUserInfoDao.update(appUserInfoPOS.get(0));
            }
            //已存在用户，判断用户-项目关系是否存在(app_user_project)
            List<AppUserProjectPO> userProjectPOS = iPropertyAppUserProjectDao.getUserAtProjectByPhoneNum(param);
            if (userProjectPOS != null && !userProjectPOS.isEmpty()){
                if (!NumberHandlerUtil.isEqual(userProjectPOS.get(0).getStatus(), DataStatusEnum.NORMAL.getType())){
                    userProjectPOS.get(0).setStatus(DataStatusEnum.NORMAL.getType());
                    userProjectPOS.get(0).setUpdateTime(new Date());
                    iPropertyAppUserProjectDao.update(userProjectPOS.get(0));
                }
                //用户-项目关系已存在，则添加/更新电梯权限(device_elevator_auth)
                this.saveOrUpdateElevatorAuth(authFloorDTO, userProjectPOS.get(0).getUserId());
            }else {
                resultMap.put("isNewUserProject", true);//该项目下的新用户

                //保存住户项目信息
                this.saveAppUserProject(appUserInfoPOS.get(0).getUserId(), authFloorDTO.getProjectId(), authFloorDTO.getCardNum());
                //保存电梯权限(device_elevator_auth)
                this.saveOrUpdateElevatorAuth(authFloorDTO, appUserInfoPOS.get(0).getUserId());
            }
        }else {
            //不存在用户则添加(app_user_info)
            AppUserInfoPO appUserInfoPO = new AppUserInfoPO();
            String userId = LogicIdUtil.userBusinessId();
            Date date = new Date();
            appUserInfoPO.setUserId(userId);
            appUserInfoPO.setRealName(authFloorDTO.getAuthUserName());
            appUserInfoPO.setPhoneNum(authFloorDTO.getAuthPhoneNo());
            appUserInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
            appUserInfoPO.setCreateTime(date);
            appUserInfoPO.setUpdateTime(date);
            iPropertyAppUserInfoDao.save(SqlUtil.durableData(appUserInfoPO, PlatformConstants.TABLE_SAVE));

            resultMap.put("isNewUser", true);//新用户
            resultMap.put("isNewUserProject", true);//该项目下的新用户
            resultMap.put("userId", userId);//返回用户id
            //添加用户-项目关系(app_user_project)
            this.saveAppUserProject(userId, authFloorDTO.getProjectId(), authFloorDTO.getCardNum());
            //添加电梯权限(device_elevator_auth)
            this.saveOrUpdateElevatorAuth(authFloorDTO, userId);
        }
        return resultMap;
    }

    /**
     * <desc>
     * 旧一卡通_授权电梯
     * <desc/>
     *
     * @param authFloorDTO 电梯权限
     * @return
     * @author Chunjian.G
     * @createDate 2017-12-09
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer authFloor(SmartCardOldAuthFloorDTO authFloorDTO, Integer isSmartCommunity) throws Exception {
        //1.保存用户权限数据
        Map<String, Object> resultMap = this.authFloorTrans(authFloorDTO);
        //2.若该项目启用了云对讲,且为该项目下的新用户，需发送同步sip消息
        if ((boolean) resultMap.get("isNewUserProject")){
            this.sendSipSyncMessage((String) resultMap.get("userId"), isSmartCommunity, authFloorDTO.getProjectId());
        }
        //3.原本已存在的用户需发送权限变更消息
        if (!(boolean) resultMap.get("isNewUser")){
            this.sendMessageForUserAuthChanged((String) resultMap.get("userId"), authFloorDTO.getProjectId());
        }
        return 1;
    }

    /**
     * <desc>
     *      从缓存获取用户信息
     * </desc>
     *
     * @param token
     * @return
     * @author shengen.T
     * @createDate 2017/10/19
     */
    @Override
    public SmartCardOldLoginVO retrieve(String token) throws Exception{
        try {
            if (StringUtils.isBlank(token)) {
                return null;
            }
            //解密拿到userId
            String account = UserTokenUtil.tokenDecrypt(token,userTokenKey );
            if (account == null) {
                return null;
            }
            String vloginString = redisService.get(RedisConstant.OLD_APP_USER_VO_KEY+account);
            SmartCardOldLoginVO vlogin = JSONObject.parseObject(vloginString,SmartCardOldLoginVO.class);
            if (vlogin != null && token.equals(vlogin.getToken())) {
                return vlogin;
            } else {
                return null;
            }
        }catch (RedisConnectionFailureException e){
            throw new DataAccessException("旧一卡通retrieve【从缓存中获取账户信息】redis连接失败") ;
        }
    }


}
